package online.heycm.lock;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.ReadMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.util.StringUtils;

/**
 * Redisson哨兵模式自动装配
 *
 * @author heycm
 * @since 2023/1/27 15:46
 */
@Slf4j
// @Configuration 通过@EnableDistributedLock加载
@ConditionalOnProperty(value = "spring.data.redis.sentinel.master")
@EnableConfigurationProperties(RedisSentinelProperties.class)
public class RedisSentinelLockAutoConfiguration {

    private static final String REDIS_PREFIX = "redis://";

    @Autowired
    private RedisSentinelProperties properties;

    public RedisSentinelLockAutoConfiguration() {
        log.info("RedisSentinelLockAutoConfiguration init...");
    }

    @Bean
    public RedissonClient redissonClient() {
        String[] nodeStr = properties.getNodes().split(",");
        List<String> newNodes = new ArrayList<>(nodeStr.length);
        Arrays.stream(nodeStr).forEach(index -> newNodes.add(
                index.startsWith(REDIS_PREFIX) ? index : REDIS_PREFIX + index));

        Config config = new Config();
        config.useSentinelServers()
                .addSentinelAddress(newNodes.toArray(new String[0]))
                .setMasterName(properties.getMaster())
                .setReadMode(ReadMode.SLAVE)
                .setUsername(StringUtils.hasText(properties.getUsername()) ? properties.getUsername() : null)
                .setPassword(StringUtils.hasText(properties.getPassword()) ? properties.getPassword() : null);
        return Redisson.create(config);
    }

    @Bean
    public RedisLock redisLock(RedissonClient redissonClient) {
        return new RedisLockImpl(redissonClient);
    }
}
